<template>
  <div class="d-flex">
    <div :class="firstIndex > -1 && 'border-right'">
      <el-scrollbar
        v-if="firstOptions.length"
        tag="ul"
        wrap-class="c-area-dropdown__wrap"
        view-class="el-select-dropdown__list"
        ref="scrollbarFirst"
      >
        <li v-if="firstOptions.length" class="el-cascader-node">
          <el-checkbox
            :indeterminate="firstAllIndeterminate"
            v-model="firstAllChecked"
            @change="handleAllItemChecked"
          >
            <div class="c-area__label-text pl-1">全选</div>
          </el-checkbox>
        </li>
        <li
          v-for="(item, index) in firstOptions"
          :key="item.id"
          class="el-cascader-node"
          :class="{ 'is-active': item.checked, 'in-checked-path': firstIndex === index }"
          @click.stop="handleFirstItemClick(item, index)"
        >
          <el-checkbox
            :indeterminate="item.indeterminate"
            v-model="item.checked"
            @click.native.stop
            @change="handleFirstItemChecked(item, index)"
          ></el-checkbox>
          <span class="c-area__label">{{ item.geo_name }}</span>
          <template v-if="hasSecondPanel">
            <i v-if="item.loading" class="el-icon-loading el-cascader-node__postfix"></i>
            <i v-else class="el-icon-arrow-right el-cascader-node__postfix"></i>
          </template>
        </li>
      </el-scrollbar>
      <div v-else-if="!loading" class="c-area__empty-text">{{ noDataText || '' }}</div>
    </div>

    <div v-if="firstIndex > -1 && hasSecondPanel">
      <el-scrollbar
        v-if="secondOptions.length"
        tag="ul"
        wrap-class="c-area-dropdown__wrap"
        view-class="el-select-dropdown__list"
        ref="scrollbarSecond"
      >
        <li
          v-for="(item, index) in secondOptions"
          :key="item.id"
          class="el-cascader-node"
          :class="{ 'is-active': item.isChecked, 'in-checked-path': item.inCheckedPath }"
          @click.stop
        >
          <el-checkbox
            :indeterminate="item.indeterminate"
            v-model="item.checked"
            @change="handleSecondItemChecked(item, index)"
          >
            <div class="c-area__label-text">{{ item.geo_name }}</div>
          </el-checkbox>
        </li>
      </el-scrollbar>
      <div v-else-if="!loading" class="c-area__empty-text">{{ noDataText || '' }}</div>
    </div>
  </div>
</template>

<script>
import { promise } from '@/common/utils/common'
import { getData } from '@vimi/utils-api'
import { mapGetters } from 'vuex'
import { addressStructure, addressCut, addressLevel, cascaderTree } from '@vimi/utils-tool'

export default {
  components: {},
  props: {
    value: {
      type: Array,
      default() {
        return []
      },
    },
    noDataText: String,
  },
  model: {
    prop: 'value',
    event: 'change',
  },
  data() {
    return {
      loading: false,
      firstOptions: [],
      secondOptions: [],
      firstAllChecked: false,
      firstAllIndeterminate: false,
      firstIndex: -1,
      secondIndex: -1,
      topOption: {},
    }
  },
  computed: {
    ...mapGetters(['user']),
    topCode() {
      return this.user.queryAddressCode
    },
    topLevel() {
      return addressLevel(this.topCode)
    },
    hasSecondPanel() {
      return this.topLevel === 0
    },
    isCounty() {
      return this.user.orgRegionLever > 2
    },
  },
  watch: {
    value: {
      handler: function (val) {
        val = val.map(it => (typeof it === 'string' ? it : it.id))

        this.changeAll(false)
        this.$emit('init', [])

        this.initValue(val, true)
      },
      immediate: true,
      deep: true,
    },
  },
  created() {
    this.getAddress()
  },
  mounted() {},
  methods: {
    initValue(val, emit = false) {
      const checkList = []
      const temp = [...val]

      this.firstAllChecked = temp.length === 1 && temp[0] === this.topOption.id
      if (this.firstAllChecked) {
        this.changeAll(this.firstAllChecked)
        checkList.push(this.topOption)
      } else {
        for (const firstItem of this.firstOptions) {
          if (!temp.length) break
          const { children = [] } = firstItem
          const i = temp.findIndex(t => t === firstItem.id)
          if (i > -1) {
            firstItem.checked = true
            checkList.push(firstItem)
            for (const child of children) {
              child.checked = true
            }
            temp.splice(i, 1)
          } else {
            let hasSecondSelect = false
            for (const child of children) {
              const j = temp.findIndex(t => t === child.id)
              if (j > -1) {
                hasSecondSelect = true
                child.checked = true
                checkList.push(child)
                temp.splice(j, 1)
              }
            }
            firstItem.indeterminate = hasSecondSelect
          }
        }
      }
      if (emit) {
        this.$emit('init', checkList)
      }
    },
    async getAddress() {
      if (this.firstOptions.length) return

      // 开始级别由用户级别决定
      // 最大级别为3
      const levers = []
      for (let i = this.topLevel; i < 3; i++) {
        levers.push(i + 1)
      }
      let startSum = 0
      for (let i = 0; i < this.topLevel + 2; i++) {
        startSum += addressStructure[i]
      }

      this.loading = true
      const [res] = await promise(
        getData('industrial_db', 'geo_codings', {
          'region_lever.in': levers.join(','),
          fields: 'id,geo_name',
          'id.endlike': addressCut(this.topCode),
        })
      )
      this.loading = false

      const resData = (res && res.data) || []
      const index = resData.findIndex(item => item.id === this.topCode)
      if (index > -1) {
        this.topOption = resData[index]
        resData.splice(index, 1)
      }

      const data = cascaderTree({
        data: resData.map(item => ({
          ...item,
          indeterminate: false,
          checked: false,
          loading: false,
          inCheckedPath: false,
        })),
        structure: [startSum, 12 - startSum],
      })
      this.firstOptions = data
      this.initValue(this.value, true)
      if (this.isCounty) {
        this.firstOptions = [{ ...this.topOption }]
        this.changeAll(true)
        this.emitChange()
      }
    },
    handleAllItemChecked(val = true) {
      this.changeAll(val)
      this.emitChange()
    },
    handleFirstItemChecked(row, index) {
      row.indeterminate = false
      this.changeFirst(row, index)
      this.refreshChildren(row)
      this.emitChange()
    },
    handleFirstItemClick(row, index) {
      this.firstIndex = index
      this.secondIndex = -1
      this.secondOptions = row.children || []
    },
    handleSecondItemChecked(row) {
      if (this.firstIndex > -1) {
        const firstOption = this.firstOptions[this.firstIndex]
        firstOption.indeterminate = this.isIndeterminate(firstOption.children)
        const firstNextChecked = !firstOption.indeterminate && row.checked
        if (firstOption.checked !== firstNextChecked) {
          firstOption.checked = firstNextChecked
          this.changeFirst(firstOption, this.firstIndex)
        }
      }
      this.emitChange()
    },
    emitChange() {
      this.$emit('change', this.getCheckedList(this.firstOptions))
    },
    changeAll(val) {
      this.firstIndex = -1
      this.firstAllIndeterminate = false
      for (const firstItem of this.firstOptions) {
        firstItem.indeterminate = false
        firstItem.checked = val
        const { children = [] } = firstItem
        for (const child of children) {
          child.indeterminate = false
          child.checked = val
        }
      }
    },
    changeFirst(row, index) {
      this.firstAllIndeterminate = this.isIndeterminate(this.firstOptions)
      this.firstAllChecked = !this.firstAllIndeterminate && row.checked
      this.handleFirstItemClick(row, index)
    },
    refreshChildren(row) {
      if (!row.children) return
      for (const child of row.children) {
        child.checked = row.checked
      }
    },
    isIndeterminate(data) {
      const { length } = data
      if (!length) return false
      for (let i = 1; i < length; i++) {
        if (data[i - 1].checked !== data[i].checked) {
          return true
        }
      }
      return false
    },
    getCheckedList(options) {
      if (this.firstAllChecked) {
        return [this.topOption]
      }

      const res = []
      for (const option of options) {
        if (option.checked) {
          res.push({
            id: option.id,
            geo_name: option.geo_name,
          })
          if (option.all) {
            break
          }
        } else {
          const { children } = option
          if (children && children.length) {
            res.push(...this.getCheckedList(children))
          }
        }
      }
      return res
    },
    removeNode() {
      //
    },
  },
}
</script>

<style lang="scss" scoped>
.c-area__empty-text {
  margin: 10px 0;
  padding: 145px 0;
  color: $gray-600;
  min-width: 200px;
  text-align: center;
}
.c-area__label {
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  min-width: 155px;
}
.c-area__label-text {
  min-width: 155px;
}
.in-checked-path {
  color: $primary;
}
</style>
